﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using CI.Misc;
using CI.Organism;

namespace CI.MSRoboticsEnv
{
    public class MudMapViewModel : DataModel, IView
    {
        private readonly ObservableCollection<OrganismDrawModel> _organismModels = new ObservableCollection<OrganismDrawModel>();
        public ObservableCollection<OrganismDrawModel> OrganismModels
        {
            get { return _organismModels; }
        }

        private IOrganism _currentlySelectedItem;
        private readonly UIConainerSize _uiContainer;
        private readonly SimEnv _simEnv = SimEnv.Instance;

        public MudMapViewModel(UserControl userControl)
        {
            UIDispatcher = Dispatcher.CurrentDispatcher;
            _simEnv.OnMainLoopStartEvent += ScenarioStart;
            _simEnv.OnMainLoopEndEvent += ScenarioEnd;
            _simEnv.OnSetSelectedOrganismEvent += SetSelectedItem;
            userControl.SizeChanged += ControlSizeChanged;
            _uiContainer = new UIConainerSize(userControl.Height, userControl.Width);
        }

        void ControlSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            _uiContainer.ContainerHeight = e.NewSize.Height;
            _uiContainer.ContainerWidth = e.NewSize.Width;
        }

        void SetSelectedItem(IOrganism selectedOrganism)
        {
            OrganismDrawModel foundCurrentOrganism;
            OrganismDrawModel newCurrentOrganism;
            lock (_organismModels)
            {
                foundCurrentOrganism = _organismModels.FirstOrDefault(o => o.Organism == _currentlySelectedItem);
                newCurrentOrganism = _organismModels.FirstOrDefault(o => o.Organism == selectedOrganism);
            }

            if (foundCurrentOrganism != null && foundCurrentOrganism.Organism.Born)
            {
                foundCurrentOrganism.BrushColour = Brushes.Black;
            }

            if (newCurrentOrganism != null && newCurrentOrganism.Organism.Born)
            {
                newCurrentOrganism.BrushColour = Brushes.Red;
            }

            _currentlySelectedItem = selectedOrganism;
        }

        private void ScenarioEnd()
        {
            if (_simEnv.HostEnv == null) 
                return;

            _simEnv.HostEnv.Organisms.OnAliveAddEvent -= AddNewOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnAliveRemoveEvent -= DeleteOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnDeadAddEvent -= AddNewOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnDeadRemoveEvent -= DeleteOrganismDrawModel;
        }

        private void ScenarioStart()
        {
            UIDispatcher.BeginInvoke(new Action(() => ClearAndAddOrganismModelsToCollection(_simEnv.HostEnv.Organisms, OrganismModels)));

            _simEnv.HostEnv.Organisms.OnAliveAddEvent += AddNewOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnAliveRemoveEvent += DeleteOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnDeadAddEvent += AddNewOrganismDrawModel;
            _simEnv.HostEnv.Organisms.OnDeadRemoveEvent += DeleteOrganismDrawModel;
        }

        private void DeleteOrganismDrawModel(IOrganism organism)
        {
            UIDispatcher.BeginInvoke(new Action(() =>
                                               {
                                                   lock (_organismModels)
                                                   {
                                                       var foundOrganismModel = _organismModels.FirstOrDefault(x => x.Organism == organism);
                                                       _organismModels.Remove(foundOrganismModel);
                                                       foundOrganismModel.Dispose();
                                                   }
                                               }));
        }

        private void AddNewOrganismDrawModel(IOrganism organism)
        {
            UIDispatcher.BeginInvoke(new Action(() =>
                                               {
                                                   lock (_organismModels)
                                                       _organismModels.Add(new OrganismDrawModel(organism, _uiContainer));
                                               }));
        }

        private void ClearAndAddOrganismModelsToCollection(IEnumerable<IOrganism> newOrganisms, ICollection<OrganismDrawModel> organismsList)
        {
            lock (_organismModels)
            {
                // clean up old ones
                foreach (var organismModel in organismsList)
                {
                    organismModel.Dispose();
                }

                organismsList.Clear();

                foreach (var organism in newOrganisms)
                {
                    organismsList.Add(new OrganismDrawModel(organism, _uiContainer));
                }
            }
        }

        public void Dispose()
        {
            lock (_organismModels)
            {
                // clean up old ones
                foreach (var organismDrawModel in _organismModels)
                {
                    organismDrawModel.Dispose();
                }

                _organismModels.Clear();

                ScenarioEnd();
            }
        }

    }
}
